package com.smartcommunity.service.dataImport;

import com.smartcommunity.base.bean.ExceptionCode;
import com.smartcommunity.base.common.DataImport;
import com.smartcommunity.bean.constant.Constant;
import com.smartcommunity.bean.entity.ImportErrorMsg;
import com.smartcommunity.bean.entity.ImportField;
import com.smartcommunity.controller.DataImportBase;
import com.smartcommunity.dao.people.PeopleDao;
import com.smartcommunity.dao.tag.TagDao;
import com.smartcommunity.entity.people.People;
import com.smartcommunity.entity.tag.ObjectTag;
import com.smartcommunity.entity.tag.Tag;
import com.smartcommunity.exception.BusinessException;
import com.smartcommunity.log.interceptor.Log;
import com.smartcommunity.service.dataImport.model.PeopleLabelExportModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 实有人口标签模板导入
 */
@Component("peopleLabel")
@Slf4j
public class PeopleLabelImport extends DataImportBase implements DataImport {

    @Autowired
    private TagDao tagDao;

    @Autowired
    private PeopleDao peopleDao;

    /**
     * 模板类型
     */
    private String type = "实有人员标签";

    /**
     * 内容标题
     */
    private  String[] headerTitle = new String[]{"证件号码","标签"};

    /**
     * 错误信息
     */
    private  String[] headerErrorMsg = new String[]{"不能为空或系统不存在","不能为空或系统不存在"};

    /**
     * key taskId,value progress
     */
    final int cacheSize = 100000;
    Map<String, Integer> progressTag = new LinkedHashMap<String, Integer>((int) Math.ceil(cacheSize / 0.75f) + 1, 0.75f, true) {
        @Override
        protected boolean removeEldestEntry(Map.Entry<String, Integer> eldest) {
            return size() > cacheSize;
        }
    };

    @Override
    @Log(info = "人员标签模板导入")
    public String importData(List list, String villageCode,String fileName, String taskId,HttpServletResponse response) throws SQLException, IllegalArgumentException, BusinessException {
        progressTag.put(taskId,10);
        // 设置小区编码（必填）
        if (StringUtils.isBlank(villageCode)) {
            throw new IllegalArgumentException("小区编码为空！");
        }
        // 初始化导入模板信息
        ImportErrorMsg msg = getFiledInfo(type,headerTitle,headerErrorMsg);

        // 字段校验信息
        List<ImportField> fieldList = msg.getFieldList();

        // 根据小区编号获取所有的人员身份证号码
        Map<String, String> param = new HashedMap();
        param.put("villageCode",villageCode);
        List<People> peopleList = peopleDao.listPeoplesByParam(param);
        List<String> peopleNos = peopleList.stream().map(item->item.getCredentialNo()).collect(Collectors.toList());

        List<Object[]> dataList = (List<Object[]>) list;
        //存储错误信息
        List<PeopleLabelExportModel> dataListCopy = new ArrayList<>();
        int size = dataList.size();
        int errorCount = 0;

        List<ObjectTag> tagList = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            boolean isError = false;

            Object[] objects = dataList.get(i);
            int currentRow = Constant.START_ROW + i;

            StringBuffer errorMessages = new StringBuffer();
            // 设置证件号（必填）
            String idCard = (String) objects[0];
            //判断身份证是否存在
            if (StringUtils.isBlank(idCard) || !peopleNos.contains(idCard)) {
                //添加错误的行数
//                SetErrorRow(headerTitle[0],currentRow,fieldList);
                String errorMsg = appendErrorMsg(fieldList.get(0).getTitle(), idCard, fieldList.get(0).getErrorMsg());
                errorMessages.append(errorMsg);
                isError = true;
            }

            // 设置标签（必填）
            String tagName = (String) objects[1];
            Tag tag = new Tag() ;
            if (StringUtils.isBlank(tagName)) {
                //添加错误的行数
//                SetErrorRow(headerTitle[1],currentRow,fieldList);
                String errorMsg = appendErrorMsg(fieldList.get(1).getTitle(), tagName, fieldList.get(1).getErrorMsg());
                errorMessages.append(errorMsg);
                isError = true;
            }else{
                //Excel模板里面标签,在数据库可能查询不到的情况
                tag = tagDao.queryByName(tagName);
                if(tag == null){
//                    SetErrorRow(headerTitle[1],currentRow,fieldList);
//                    isError = true;
                    //由于数据库和excel中的标签可能不同步，暂时先不做校验，直接跳过
                    continue;
                }
            }

            //判断当前行是否有错误
            if(isError){
                errorCount++;
                PeopleLabelExportModel exportModel = new PeopleLabelExportModel();
                exportModel.setIdCard(idCard);
                exportModel.setTagName(tagName);
                exportModel.setErrorMsg(errorMessages.toString());
                dataListCopy.add(exportModel);
            }else{
                // 加入标签列表
                ObjectTag ot = new ObjectTag(idCard,villageCode,tag.getId());
                tagList.add(ot);
            }
        }

        // 入库人员标签信息
        try {
            if(CollectionUtils.isNotEmpty(tagList)) {
                progressTag.put(taskId,60);
                tagDao.addObjectTag(tagList);
            }
            //正常的数据需要导入进去，错误的数据返回到Excel
            if (errorCount>0) {
                String errorFileName = exportExcelToLocal(taskId,fileName,headerTitle,dataListCopy);
                progressTag.put(taskId,100);
                return errorFileName;
            }
        } catch (Exception e) {
            log.error("导入实有人员标签失败，保存数据库异常！", e);
            throw new BusinessException(ExceptionCode.PEOPLE_SQL_EXCEPTION_CODE,"导入实有人员标签失败，保存数据库异常！");
        }
        log.info("实有人员标签导入完成");
        progressTag.put(taskId, 100);
        return "";
    }

    @Override
    public int getImportDataProgress(String taskId) {
        return progressTag.get(taskId) == null ? 0 : progressTag.get(taskId);
    }
}
